package de.dailab.graphworld.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JTextField;

import de.dailab.graphworld.ontology.Graph;
import de.dailab.graphworld.ontology.Node;

public class GraphWorldMenuBar extends JMenuBar {

	private static final long serialVersionUID = -4353821389161173562L;

	private GraphWorldGUI gui;
	
	final JMenu mFile = new JMenu("File");
	final JMenu mEditor = new JMenu("Editor");
	final JMenu mSupp = new JMenu("Support");
	
	final JMenuItem miRandom = new JMenuItem("Create Random Graph");
	final JMenuItem miLoad = new JMenuItem("Load Graph");
	final JMenuItem miSave = new JMenuItem("Save Graph");
	final JMenuItem miExit = new JMenuItem("Exit Editor");
	final JMenuItem miAbout = new JMenuItem("About");
	final JMenuItem miHelp = new JMenuItem("Help");
	final JMenuItem miCreate = new JMenuItem("Create New Graph");
	final JMenuItem miAddNode = new JMenuItem("Add Node");
	final JMenuItem miAddEdge = new JMenuItem("Edit Edge");
	final JMenuItem miRemNode = new JMenuItem("Remove Last Node");
	final JMenuItem miSetGold = new JMenuItem("Set Gold");
	
	public GraphWorldMenuBar(GraphWorldGUI gui, boolean editormode){
		
		this.gui = gui;
		createMenuBar();
		
        mFile.add(miLoad);  
        mFile.add(miSave);
        mFile.addSeparator();
		mFile.add(miExit);
		mEditor.add(miCreate);
        mEditor.add(miRandom);
        mEditor.addSeparator();
		mEditor.add(miAddNode);
		mEditor.add(miRemNode);
		mEditor.add(miAddEdge);
		mEditor.add(miSetGold);
        mSupp.add(miAbout); 
        if(editormode)
        	mSupp.add(miHelp);    
        
        miRemNode.setEnabled(false);
        miSetGold.setEnabled(false);
        miAddEdge.setEnabled(false);
        miAddNode.setEnabled(false);
        
        if(editormode){
        	this.add(mFile);
			this.add(mEditor);
        }
        this.add(mSupp);
	}
	
	private void createMenuBar() {
		
		// create menus
        mFile.setMnemonic('F');   
		mEditor.setMnemonic('E');
        mSupp.setMnemonic('S');
        
        // create menuitems
        miRandom.setMnemonic('R');
        miLoad.setMnemonic('L');
        miSave.setMnemonic('S');
        miExit.setMnemonic('X');
        miAbout.setMnemonic('A');
        miHelp.setMnemonic('H');
        miCreate.setMnemonic('C');
        miAddNode.setMnemonic('N');
        miAddEdge.setMnemonic('E');
        miRemNode.setMnemonic('L');
        miSetGold.setMnemonic('G');
        
        // add actionlisteners
        // create random graph
        miRandom.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
        		System.out.println(""+JOptionPane.OK_OPTION+"  "+JOptionPane.YES_OPTION);
        		int retVar = JOptionPane.showConfirmDialog(gui,"Create random graph?\nThe old graph will be discarded.","Confirm",JOptionPane.YES_NO_OPTION,JOptionPane.WARNING_MESSAGE);
        		if(retVar == JOptionPane.OK_OPTION){
        			gui.setGraph(new Graph(new Random(),25));
    				updateMenu();
        		}
        	}
        });
        // load graph
        miLoad.addActionListener(new ActionListener() {
        	@Override
        	public void actionPerformed(ActionEvent arg0) {
        		int approve;
        		if(gui.graph != null){
        			approve = JOptionPane.showConfirmDialog(gui,"Load graph?\nThe old graph will be discarded.","Confirm",JOptionPane.YES_NO_OPTION,JOptionPane.WARNING_MESSAGE);
        		} else {
        			approve = JOptionPane.YES_OPTION;
        		}
        		if(approve == JOptionPane.YES_OPTION){
	        		JFileChooser fc = new JFileChooser();
	    			int retVar = fc.showOpenDialog(gui);
	    			if (retVar == JFileChooser.APPROVE_OPTION) {
	    				gui.load(fc.getSelectedFile());
	    				updateMenu();
	    			}
    			} else {
    				JOptionPane.showMessageDialog(gui,"Loading aborted","User input",JOptionPane.INFORMATION_MESSAGE);
    			}
        	}
        });
        // save graph
        miSave.addActionListener(new ActionListener() {
        	@Override
        	public void actionPerformed(ActionEvent arg0) {
        		gui.save();
        	}
        });
        // exit program
        miExit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                @SuppressWarnings("unused")
				GraphWorldLauncher gwl = new GraphWorldLauncher();
                gui.dispose();
            }
        });
        // create empty graph to edit
        miCreate.addActionListener(new ActionListener() {
			@Override
            public void actionPerformed(ActionEvent arg0) {
            	try{
            		int retVar = JOptionPane.showConfirmDialog(gui,"Create new graph?\nThe old graph will be discarded.","Confirm",JOptionPane.YES_NO_OPTION,JOptionPane.WARNING_MESSAGE);
            		if(retVar == JOptionPane.OK_OPTION){
	            		gui.setGraph(new Graph());
		        		updateMenu();
            		}
				}catch(Exception e){
					JOptionPane.showMessageDialog(gui,"Wrong input.","Error",JOptionPane.ERROR_MESSAGE);
				}
            }
        });
        // add node in a graph
        miAddNode.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				try{
					JTextField xCoord = new JTextField();
	                JTextField yCoord = new JTextField();
	                Object[] message = {"x-coordinate", xCoord,"y-coordinate", yCoord};
	                int retVar = JOptionPane.showOptionDialog(gui, message, "Add Edge", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
                	if(retVar == JOptionPane.OK_OPTION) {
		                int x = Integer.parseInt(xCoord.getText());
		                int y = Integer.parseInt(yCoord.getText());
		                if(x>=0 && y>=0){
		                	gui.graph.addNode(x, y, 0);
							gui.update();
							updateMenu();
		                }else{
		                	JOptionPane.showMessageDialog(gui,"Only positive values allowed.","Error",JOptionPane.ERROR_MESSAGE);
		                }
                	}
				}catch(Exception e){
					JOptionPane.showMessageDialog(gui,"Wrong input.","Error",JOptionPane.ERROR_MESSAGE);
				}
			}
		});
        // add edge in a graph
		miAddEdge.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				try{
					JTextField firstID = new JTextField();
	                JTextField secondID = new JTextField();
	                JTextField distance = new JTextField();
	                Object[] message = {"From node", firstID,"To node", secondID, "Weight", distance};
	                int retVar = JOptionPane.showOptionDialog(gui, message, "Edit Edge", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
					if(retVar == JOptionPane.OK_OPTION){
						gui.graph.editEdge(Integer.parseInt(firstID.getText()), Integer.parseInt(secondID.getText()), Short.parseShort(distance.getText()));
						gui.update();
						updateMenu();
					}
				}catch(Exception e){
					JOptionPane.showMessageDialog(gui,"Wrong input.","Error",JOptionPane.ERROR_MESSAGE);
				}
			}
		});
		// remove last created node
        miRemNode.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				try{
					int retVal = JOptionPane.showConfirmDialog(gui,"Remove node with ID="+gui.graph.getNodes().get(gui.graph.getNodes().size()-1).getID()+" ?\nEdges will be removed automatically.","Remove Node",JOptionPane.YES_NO_OPTION,JOptionPane.WARNING_MESSAGE);
					if(retVal == JOptionPane.YES_OPTION){
						gui.graph.removeLastNode();
		        		updateMenu();
						gui.update();
					}
				}catch(Exception e){
					JOptionPane.showMessageDialog(gui,"Wrong input.","Error",JOptionPane.ERROR_MESSAGE);
				}
			}
		});
        // set gold value on a node
        miSetGold.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				JTextField nodeID = new JTextField();
                JTextField gold = new JTextField();
                Object[] message = {"Node ID", nodeID,"Units of Gold", gold};
                int retVar = JOptionPane.showOptionDialog(gui, message, "Set Gold Amount", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
				if(retVar == JOptionPane.OK_OPTION){
					gui.graph.getNodes().get(Integer.parseInt(nodeID.getText())).setGold(Integer.parseInt(gold.getText()));
					gui.update();
				}
			}
		});
        // get release infos
        miAbout.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				System.out.println("release infos");
			}
		});
        // get help data
        miHelp.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				System.out.println("Nobody will help - abandon all hope!");
			}
		});
	}
	
	private void updateMenu(){
		
		// check if graph exists
		boolean b = (gui.graph != null);
		
		// check if any edges exist
		boolean e = false;
		if(b){
			for(Node n : gui.graph.getNodes()){
				if(!n.getEdges().isEmpty()){
					e = true;
					break;
				}
			}
		}
		
		// remove nodes and change gold only when nodes exist
		miRemNode.setEnabled(b && gui.graph.getNodes().size()>0);
		miSetGold.setEnabled(b && gui.graph.getNodes().size()>0);
		
		// add edges only when at least two nodes exist
		miAddEdge.setEnabled(b && gui.graph.getNodes().size()>1);
		
		// start/save only when a graph with edges exists
    	miSave.setEnabled(e);

		// add node only when graph exists
		miAddNode.setEnabled(b);
	}

}
